using FytSoa.Application.Erp.Param;
using FytSoa.Domain.Erp;
using FytSoa.Sugar;
using FytSoa.Common.Utils;
using FytSoa.Common.Param;
using FytSoa.Common.Result;
using Mapster;
using Masuit.Tools;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace FytSoa.Application.Erp;

/// <summary>
/// erp-仓库产品表服务接口
/// </summary>
[ApiExplorerSettings(GroupName = "v9")]
public class ErpWarehouseProductService : IApplicationService 
{
    private readonly SugarRepository<ErpWarehouseProduct> _thisRepository;
    public ErpWarehouseProductService(SugarRepository<ErpWarehouseProduct> thisRepository)
    {
        _thisRepository = thisRepository;
    }
    
    /// <summary>
    /// 查询所有——分页
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ErpWarehouseProductInfoDto>> GetPagesAsync(ErpWarehouseProductParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(param.WarehouseId),m=>m.WarehouseId==long.Parse(param.WarehouseId))
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && s.Name.Contains(param.Key)).Any())
            .WhereIF(!string.IsNullOrEmpty(param.TypeId),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && s.TypeId==long.Parse(param.TypeId)).Any())
            .Includes(m=>m.Warehouse)
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        var result=query.Adapt<PageResult<ErpWarehouseProductInfoDto>>();
        if (query.Items.Count>0)
        {
            var productRepository = _thisRepository.ChangeRepository<SugarRepository<ErpProduct>>();
            var productIds = query.Items.Select(m => m.ProductId).ToList();
            var productList = await productRepository.AsQueryable()
                .Where(m => productIds.Contains(m.Id))
                .Includes(m=>m.Type)
                .Includes(m=>m.Unit)
                .Includes(m=>m.Supplier)
                .ToListAsync();
            foreach (var item in result.Items)
            {
                var productModel = productList.FirstOrDefault(m => m.Id == item.ProductId);
                if (productModel==null) continue;
                item.Product = productModel.Adapt<ErpProductDto>();
            }
        }

        return result;
    }

    /// <summary>
    /// 产品详情-包括出入库数量/编号等
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<PageResult<ErpProductDetailDto>> GetDetailAsync(ErpWarehouseProductParam param)
    {
        var query = await _thisRepository.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(param.WarehouseId),m=>m.WarehouseId==long.Parse(param.WarehouseId))
            .WhereIF(!string.IsNullOrEmpty(param.Key),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && (s.Name.Contains(param.Key) || s.Number.Contains(param.Key))).Any())
            .WhereIF(!string.IsNullOrEmpty(param.TypeId),m=>
                SqlFunc.Subqueryable<ErpProduct>().Where(s => s.Id == m.ProductId && s.TypeId==long.Parse(param.TypeId)).Any())
            .Includes(m=>m.Warehouse)
            .OrderByDescending(m=>m.Id)
            .ToPageAsync(param.Page, param.Limit);
        var result=query.Adapt<PageResult<ErpProductDetailDto>>();
        if (query.Items.Count>0)
        {
            var productRepository = _thisRepository.ChangeRepository<SugarRepository<ErpProduct>>();
            var productIds = query.Items.Select(m => m.ProductId).ToList();
            var productList = await productRepository.AsQueryable()
                .Where(m => productIds.Contains(m.Id))
                .Includes(m=>m.Type)
                .Includes(m=>m.Unit)
                .Includes(m=>m.Supplier)
                .ToListAsync();
            var productDto = productList.Adapt<List<ErpProductDto>>();
            var stockIds = result.Items.Select(m => m.WarehouseId);

            //根据商品和仓库查询出库编码、时间、数量
            var outstockProductRepository=_thisRepository.ChangeRepository<SugarRepository<ErpOutstockProduct>>();
            var outStockProductList = await outstockProductRepository.AsQueryable()
                .Where(m => productIds.Contains(m.ProductId) && 
                            SqlFunc.Subqueryable<ErpOutstock>().Where(o=>stockIds.Contains(o.WarehouseId)).Any())
                .Includes(m=>m.OutStock)
                .ToListAsync();
            
            //根据商品和仓库查询入库编码、时间、数量
            var inStockProductRepository=_thisRepository.ChangeRepository<SugarRepository<ErpInstockProduct>>();
            var inStockProductList = await inStockProductRepository.AsQueryable()
                .Where(m => productIds.Contains(m.ProductId) && 
                            SqlFunc.Subqueryable<ErpOutstock>().Where(o=>stockIds.Contains(o.WarehouseId)).Any())
                .Includes(m=>m.InStock)
                .ToListAsync();
            
            
            foreach (var item in result.Items)
            {
                var product = productDto.FirstOrDefault(m => m.Id == item.ProductId);
                if (product==null) continue;
                var inStockModel = inStockProductList.FirstOrDefault(m => m.ProductId == product.Id && m.WarehouseId==item.WarehouseId);
                if (inStockModel==null)
                {
                    inStockModel = inStockProductList.FirstOrDefault(m => m.ProductId == product.Id);
                }
                
                item.Id = product.Id;
                item.Name = product.Name;
                item.Number = product.Number;
                item.Price = product.Price;
                item.MarketPrice = product.MarketPrice;
                item.Unit = product.Unit;
                item.Type = product.Type;
                item.OutNumber = outStockProductList.FirstOrDefault(m => m.ProductId==product.Id && m.WarehouseId==item.WarehouseId)?.OutStock.Number;
                item.OutTime= outStockProductList.FirstOrDefault(m => m.ProductId==product.Id && m.WarehouseId==item.WarehouseId)?.CreateTime;
                item.OutCount = outStockProductList.Where(m => m.ProductId==product.Id && m.WarehouseId==item.WarehouseId).Sum(m=>m.Count);
                item.InNumber = inStockModel?.InStock.Number;
                item.InTime= inStockModel?.CreateTime;
                item.InCount = inStockProductList.Where(m => m.ProductId==product.Id && m.WarehouseId==item.WarehouseId).Sum(m=>m.Count);
            }
        }
        
        return result;
    }

    /// <summary>
    /// 根据主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<ErpWarehouseProductDto> GetAsync(long id)
    {
        var model = await _thisRepository.GetByIdAsync(id);
        return model.Adapt<ErpWarehouseProductDto>();
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task AddAsync(List<ErpWarehouseProduct> param)
    {
        var productIds = param.Select(m => m.ProductId).ToList();
        var addList = new List<ErpWarehouseProduct>();
        var updateList = new List<ErpWarehouseProduct>();
        var productList = await _thisRepository.GetListAsync(m => productIds.Contains(m.ProductId));
        foreach (var item in param)
        {
            var product = productList.FirstOrDefault(m => m.ProductId == item.ProductId && m.WarehouseId==item.WarehouseId);
            if (product!=null)
            {
                product.Count += item.Count;
                updateList.Add(product);
            }
            else
            {
                addList.Add(item);
            }
        }
        if (addList.Count>0)
        {
            await _thisRepository.InsertRangeAsync(addList);
        }

        if (updateList.Count>0)
        {
            await _thisRepository.UpdateRangeAsync(updateList);
        }
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<bool> ModifyAsync(ErpWarehouseProductDto model) =>
        await _thisRepository.UpdateAsync(model.Adapt<ErpWarehouseProduct>());

    /// <summary>
    /// 删除,支持批量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [HttpDelete]
    public async Task<bool> DeleteAsync([FromBody]List<long> ids) =>
        await _thisRepository.DeleteAsync(m=>ids.Contains(m.Id));
}
